package com.element.security.single.filter;

import com.common.core.constant.SecurityHeader;
import com.common.core.exception.code.SecurityErrorCode;
import com.common.core.results.VoidResult;
import com.element.security.single.constant.SecurityParams;
import com.element.security.single.model.AuthUserE;
import com.element.security.single.token.RedisTokenStore;
import com.element.security.single.utils.ResponseUtil;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Resource
    private RedisTokenStore redisTokenStore;

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain chain) throws ServletException, IOException {
        String accessToken = getToken(request);
        if (!StringUtils.hasText(accessToken)) {
            chain.doFilter(request, response);
            return;
        }
        AuthUserE authUser = redisTokenStore.get(SecurityParams.getTokenKey(accessToken), AuthUserE.class);
        if (null == authUser) {
            ResponseUtil.writeJson(response, VoidResult.failed(SecurityErrorCode.A_INVALID_TOKEN_EXCEPTION));
            return;
        }
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(authUser, null, null);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        chain.doFilter(request, response);
    }

    public String getToken(HttpServletRequest request) {
        String header = request.getHeader(SecurityHeader.AUTH_SECURITY_HEADERS);
        if (!StringUtils.hasText(header)) {
            return request.getParameter(SecurityHeader.AUTH_SECURITY_HEADERS);
        }
        if (!header.contains(SecurityHeader.AUTH_SECURITY_VALUE)) {
            return null;
        }
        String authHeaderValue = header.substring(SecurityHeader.AUTH_SECURITY_VALUE.length()).trim();
        int commaIndex = authHeaderValue.indexOf(44);
        if (commaIndex > 0) {
            authHeaderValue = authHeaderValue.substring(0, commaIndex);
        }
        return authHeaderValue;
    }
}